<?php
/**
 * Created by PhpStorm.
 * User: Len
 * Date: 2017/08/11
 * Time: 16:18
 * 脚本Demo
 */


set_time_limit(0);
ini_set('memory_limit', '50M');
date_default_timezone_set('Asia/Shanghai');

/**
 * Class CodisTransfer
 */
class DemoScript
{
    /**
     * @var \PDO
     */
    public $db;

    /**
     * @var \redis
     */
    public $redis;

    /**
     * @var
     */
    static $file_config;

    /**
     * @var
     */
    private $file_path;

    /**
     * @var
     */
    private $file_name;

    /**
     * 两秒信号量
     */
    const TMP_MAX_SECOND = 2;

    /**
     * CodisTransfer constructor.
     * @param $config
     */
    public function __construct($config)
    {
        $this->iniSystem($config);
    }

    /**
     * @param $config
     * @return DemoScript
     */
    public static function instance($config)
    {
        return new self($config);
    }

    public function run()
    {
        $tmp_time = time();
        while(true) {
            // 每次循环都相当于重置调用信号处理器
            if ((time() - $tmp_time) > static::TMP_MAX_SECOND) {
                static::dispatch();
                $tmp_time = time();
                continue;
            }
        }

    }

    private function MysqlDemo()
    {
        $sql = "SELECT * FROM table";
        try {
            $result = $this->db->query($sql);
            $result->setFetchMode(PDO::FETCH_ASSOC);
            $list = $result->fetchAll();
        } catch (\Exception $e) {
            return array();
        }

        return $list;
    }

    private function redisDemo($tag, $max_id)
    {
        $redis_key = sprintf(static::KEY_DEMO, $tag);

        return $this->redis->set($redis_key, $max_id);
    }

    private function writeMysqlDemo($user_id, $user_info)
    {
        $sql = 'INSERT INTO table (`user_id`, `type`, `nickname`, `sex`, `uniqid`, `icon`, `create_dt`) VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s")';
        $sql = sprintf($sql, $user_id, $user_info['type'], $user_info['nickname'], $user_info['sex'], $user_info['uniqid'], $user_info['icon'], $user_info['dt']);
        try {
            $num = $this->db->exec($sql);
        } catch (\Exception $e) {
            $this->errorLog('writeMysqlDemo' . $user_id . ' :' . $e->getMessage() . '; Sql: ' . $sql);
            return false;
        }

        return $num;
    }

    /**
     * @param $config
     */
    private function iniSystem($config)
    {
        $this->create_file($config['file']);
        // 自定义生成数据库连接
        $this->db = $this->create_mysql($config['mysql']);
        $this->redis = $this->create_redis($config['mysql']);
    }

    /**
     * @param $config
     */
    private function create_file($config)
    {
        $this->file_path = $config['file_path'] ?: __DIR__ . '/log/';
        $this->file_name = $config['file_name'] ?: 'default_%s.log';
    }

    /**
     * @param $config
     * @return PDO
     */
    private function create_mysql($config)
    {
        //建立mysql数据库连接
        $dsn = sprintf("mysql:host=%s;charset=%s;dbname=%s", $config['host'], $config['chartset'], $config['dbname']);
        $this->accessLog($dsn);
        try {
            $db = new \PDO($dsn, $config['user'], $config['pwd']);
            $db->query('set names utf8');
        } catch (\Exception $e) {
            $this->errorLog("connect Mysql failed: {$e->getMessage()}");
            exit('connect Mysql failed');
        }
        $this->accessLog('mysql 连接成功');

        return $db;
    }

    /**
     * @param $config
     * @return redis
     */
    private function create_redis($config)
    {
        try {
            $redis = new redis();
            $redis->connect($config['host'], $config['port']);
            $redis->select($config['db']);
        } catch (\Exception $e) {
            $this->errorLog("connect reids failed: {$e->getMessage()}");
            exit('connect Redis failed');
        }
        $this->accessLog('redis 连接成功');

        return $redis;
    }

    /**
     * 运行日志,记录运行步骤
     */
    private function accessLog($accessMessage)
    {
        //添加数据
        $accessMessage = date(DATE_RFC822) . " -access- " . $accessMessage . "\r\n";
        //调用写入函数
        return $this->addToFile($accessMessage);
    }

    /**
     * 错误日志
     */
    private function errorLog($errorMessage)
    {
        //添加必要数据
        $errorMessage = date(DATE_RFC822) . " -error- " . $errorMessage . "\r\n";
        //调用写入函数
        return $this->addToFile($errorMessage);
    }

    /**
     * 写入文件函数
     */
    private function addToFile($logMessage)
    {
        //判断存储文件策略
        $this->fileConf();
        $file_log_name = sprintf($this->file_path . $this->file_name, date('Ymd'));

        return file_put_contents($file_log_name, $logMessage, FILE_APPEND);
    }

    /**
     * 存储文件策略
     */
    private function fileConf()
    {
        //获得配置文件
        if (!file_exists($this->file_path)) {
            mkdir($this->file_path);
        }
        $file_log_name = sprintf($this->file_path . $this->file_name, date('Ymd'));
        if (!file_exists($file_log_name)) {
            touch($file_log_name);
        }

        return;
    }

    /**
     * 安装信号处理器
     */
    public static function signalConfig()
    {
        pcntl_signal(SIGUSR1, array('CodisTransfer', 'afterhandler'), false);
        pcntl_signal(SIGHUP, array('CodisTransfer', 'afterhandler'), false);
        pcntl_signal(SIGUSR2, array('CodisTransfer', 'afterhandler'), false);
        pcntl_signal(SIGINT, array('CodisTransfer', 'afterhandler'), false);
    }

    /**
     * 向当前进程发送SIGKILL信号
     * @param $signal
     */
    public static function afterhandler($signal)
    {
        echo 'SIGNAL:', $signal, PHP_EOL;
        posix_kill(posix_getpid(), SIGKILL);
    }

    /**
     * 调用等待信号的处理器
     */
    public static function dispatch()
    {
        pcntl_signal_dispatch();
    }
}

$config = array(
    'file' => [
        'file_path' => __DIR__ . '/logs/',
        'file_name' => 'test_%.log',
    ],
    'mysql' => [
        'host' => '127.0.0.1',
        'user' => 'test',
        'pwd' => '123456',
        'charset' => 'utf8',
        'dbname' => 'db_test',
    ],
    'redis' => [
        'host' => '127.0.0.1',
        'port' => 6379,
        'db' => 1
    ],

);

DemoScript::instance($config)->run();